/*
 * Copyright (c) 2024. hallele, Inc All rights reserved.
 */

package cn.hallele.mc.sdk.portalcenter.dto;

import cn.hallele.infrastructure.util.annotation.tree.Tree;
import cn.hallele.infrastructure.util.annotation.tree.TreeId;
import cn.hallele.infrastructure.util.annotation.tree.TreeParentId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;

import java.io.Serial;
import java.io.Serializable;
import java.util.List;
import java.util.function.Function;

/**
 * hallele_mc_sdk
 *
 * @author anle5
 * @since 2024/10/13 11:28
 */
@Setter
@Getter
@Builder
@NoArgsConstructor
@Schema(description = "下拉选项对象")
public class OptionDTO<T, R> implements Serializable {
    @Serial
    private static final long serialVersionUID = -6562743552631256306L;

    /**
     * 选项的值
     */
    @TreeId
    @Schema(description = "选项的值")
    private R value;

    /**
     * 选项的标签
     */
    @Schema(description = "选项的标签")
    private String label;

    /**
     * 父id
     */
    @TreeParentId
    @JsonIgnore
    private R parentId;

    /**
     * 子选项列表
     */
    @Tree
    @Schema(description = "子选项列表")
    @JsonInclude(value = JsonInclude.Include.NON_EMPTY)
    private List<OptionDTO<T, R>> children;

    /**
     * 构造函数
     *
     * @param value value
     * @param label label
     */
    public OptionDTO(R value, String label) {
        this.value = value;
        this.label = label;
    }

    /**
     * 构造函数
     *
     * @param value    value
     * @param label    label
     * @param children children
     */
    public OptionDTO(R value, String label, List<OptionDTO<T, R>> children) {
        this.value = value;
        this.label = label;
        this.children = children;
    }

    /**
     * 构造函数
     *
     * @param value    value
     * @param label    label
     * @param parentId parentId
     * @param children children
     */
    public OptionDTO(R value, String label, R parentId, List<OptionDTO<T, R>> children) {
        this.value = value;
        this.label = label;
        this.parentId = parentId;
        this.children = children;
    }

    /**
     * 构造list
     *
     * @param tList tList
     * @param label label
     * @param value value
     * @param <T>   t
     * @param <R>   r
     * @return OptionDTO list
     */
    public static <T, R> List<OptionDTO<T, R>> buildList(
            List<T> tList,
            Function<T, String> label,
            Function<T, R> value) {
        return tList.stream().map(t -> OptionDTO.<T, R>builder()
                .value(value.apply(t))
                .label(label.apply(t))
                .build()).toList();
    }

    /**
     * 构造list
     *
     * @param tList    tList
     * @param label    label
     * @param value    value
     * @param parentId parentId
     * @param children children
     * @param <T>      T
     * @param <R>      R
     * @return OptionDTO list
     */
    public static <T, R> List<OptionDTO<T, R>> buildList(
            List<T> tList,
            Function<T, String> label,
            Function<T, R> value,
            Function<T, R> parentId,
            Function<T, List<OptionDTO<T, R>>> children) {
        return tList.stream().map(t -> OptionDTO.<T, R>builder()
                .value(value.apply(t))
                .label(label.apply(t))
                .parentId(parentId == null ? null : parentId.apply(t))
                .children(children == null ? null : children.apply(t))
                .build()).toList();
    }
}
